package main

import (
	"bytes"
	"html/template"
	"log"
	"time"

	"github.com/valyala/fasthttp"

	"gitee.com/tbq_go_packages/utils"
	"github.com/savsgio/atreugo"

	"github.com/dgrijalva/jwt-go"
	"github.com/savsgio/go-logger"
)

var jwtSignKey = []byte("TestForFasthttpWithJWT")

type userCredential struct {
	Username []byte `json:"username"`
	Password []byte `json:"password"`
	jwt.StandardClaims
}

func generateToken(username []byte, password []byte) (string, time.Time) {
	logger.Debugf("Create new token for user %s", username)

	expireAt := time.Now().Add(1 * time.Minute)

	// Embed User information to `token`
	newToken := jwt.NewWithClaims(jwt.SigningMethodHS512, &userCredential{
		Username: username,
		Password: password,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expireAt.Unix(),
		},
	})

	// token -> string. Only server knows the secret.
	tokenString, err := newToken.SignedString(jwtSignKey)
	if err != nil {
		logger.Error(err)
	}

	return tokenString, expireAt
}

func validateToken(requestToken string) (*jwt.Token, *userCredential, error) {
	logger.Debug("Validating token...")

	user := &userCredential{}
	token, err := jwt.ParseWithClaims(requestToken, user, func(token *jwt.Token) (interface{}, error) {
		return jwtSignKey, nil
	})

	return token, user, err
}

type Data struct {
	Username string
}

func main() {
	config := atreugo.Config{
		Addr: "0.0.0.0:8000",
	}
	server := atreugo.New(config)

	server.GET("/", func(ctx *atreugo.RequestCtx) error {
		t, err := template.ParseFiles("./template/index.html")
		if err != nil {
			log.Fatal("Parse file template error:", err)
		}
		data := Data{Username: string(ctx.FormValue("username"))}
		buf := new(bytes.Buffer)
		err = t.Execute(buf, data)
		if err != nil {
			log.Fatal("Execute file template error:", err)
		}

		return ctx.HTTPResponse(buf.String())
	})
	server.POST("/do-login", func(ctx *atreugo.RequestCtx) error {
		jwtCookie := ctx.Request.Header.Cookie("atreugo_jwt")

		if len(jwtCookie) == 0 {
			username := string(ctx.FormValue("username"))
			password := string(ctx.FormValue("password"))

			db := utils.GetDb("mysql", "work:111111@tcp(192.168.56.1:3306)/hyperf_usercenter?charset=utf8")
			sql := "select `password`,id from users where account=?"
			row := db.SelectOne(sql, username)

			var passwordDB string
			var id int64
			row.Scan(&passwordDB, &id)
			var msg string
			var status int
			if passwordDB == password {
				jwtCookie := ctx.Request.Header.Cookie("atreugo_jwt")

				if len(jwtCookie) == 0 {
					qUser := []byte("username")
					qPasswd := []byte("password")

					tokenString, expireAt := generateToken(qUser, qPasswd)

					// Set cookie for domain
					cookie := fasthttp.AcquireCookie()
					defer fasthttp.ReleaseCookie(cookie)

					cookie.SetKey("atreugo_jwt")
					cookie.SetValue(tokenString)
					cookie.SetExpire(expireAt)
					ctx.Response.Header.SetCookie(cookie)
				}

				cookie := new(fasthttp.Cookie)
				cookie.SetKey("userid")
				cookie.SetValue(string(id))
				ctx.Response.Header.SetCookie(cookie)
				msg = "登录成功"
				status = 200
			} else {
				status = 500
				msg = "登录失败"
			}

			return ctx.HTTPResponse(msg, status)
		} else {
			return ctx.RedirectResponse("/", ctx.Response.StatusCode())
		}
	})

	if err := server.ListenAndServe(); err != nil {
		panic(err)
	}
}
